﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE;
using System.IO;
using WPLDB.Infrastucture.IO;
using WPLDB.Utility.Extensions;

namespace WPLDB.Infrastucture.Package
{
    public class PackageOperations
    {

        #region "Methods"
        /// <summary>
        /// Add DLL References into a project
        /// </summary>
        /// <param name="project"></param>
        /// <param name="listOfReferences"></param>
        /// <returns></returns>
        public bool AddReferences(Project project, IList<string> listOfReferences)
        {
            VSLangProj.VSProject vsProject = (VSLangProj.VSProject)project.Object;
            //var reff = vsProject.References;
            string referenceDirectory = Path.GetDirectoryName(vsProject.References.Find("System").Path);

            if (null != listOfReferences)
                foreach (var item in listOfReferences)
                    if (File.Exists(referenceDirectory + Path.DirectorySeparatorChar + item + ".dll"))
                        vsProject.References.Add(referenceDirectory + Path.DirectorySeparatorChar + item + ".dll");


            return true;
        }

        /// <summary>
        /// Add DLL References into a project
        /// </summary>
        /// <param name="projectItem"></param>
        /// <param name="listOfReferences"></param>
        /// <returns></returns>
        public bool AddReferences(ProjectItem projectItem, IList<string> listOfReferences)
        {
            if (null != projectItem && null != projectItem.ContainingProject)
                return AddReferences(projectItem.ContainingProject, listOfReferences);
            else
                return false;
        }

        /// <summary>
        /// Add file and its designer file content for a selected ProjectItem
        /// </summary>
        /// <param name="projectItem"></param>
        /// <param name="content"></param>
        /// <param name="fileName"></param>
        /// <param name="contentHelper"></param>
        /// <returns></returns>
        //TODO: Method Name Change
        public ProjectItem AddFolderAndFile(ProjectItem projectItem, string content, string fileName, string contentHelper)
        {
            AddReferences(projectItem, ImportNamespace.ListOfNamessapces);

            if (null != projectItem && null != projectItem.ContainingProject)
            {

                string nameSpace = GetNamespace(projectItem);
                string folder = nameSpace.LastProjectItemName();
                string projectFileName = GetClassName(projectItem);
                FileOperations fileOperations = new FileOperations();
                string directory = fileOperations.CreateTempFolder(Directory.GetParent(projectItem.Name).ToString());

                string filename = string.Format(@"{0}{1}{2}.Designer.cs", directory, Path.DirectorySeparatorChar, projectFileName.RemoveSpecialChar());
                string filenameHelper = string.Format(@"{0}{1}{2}.cs", directory, Path.DirectorySeparatorChar, projectFileName.RemoveSpecialChar());

                filename = fileOperations.Write(filename, content.Replace("[LOCALDATABASE]", ""), true);
                filenameHelper = fileOperations.Write(filenameHelper, contentHelper.Replace("[LOCALDATABASE]", ""), false);


                ProjectItem projectFolderItem = GetProjectItem(projectItem.ContainingProject.ProjectItems, folder, projectFileName);

                if (null != projectFolderItem)
                {
                    projectItem.Delete();
                    projectItem = projectFolderItem.ProjectItems.AddFromFileCopy(filenameHelper);
                }
                else
                {
                    Project project = projectItem.ContainingProject;
                    projectItem.Delete();
                    projectItem = project.ProjectItems.AddFromFileCopy(filenameHelper);
                }



                fileOperations.Delete(filename);
                fileOperations.Delete(filenameHelper);
                fileOperations.DeleteTempFolder(directory);

                return projectItem;
            }
            else
                return projectItem;
        }

        /// <summary>
        /// Add a folder and supporting files into the Project
        /// </summary>
        /// <param name="project"></param>
        /// <param name="content"></param>
        /// <param name="database"></param>
        /// <param name="contentHelper"></param>
        /// <param name="fileHelper"></param>
        /// <returns></returns>
        public bool AddFolderAndFile(Project project, string content, string database, string contentHelper, string fileHelper)
        {

            FileOperations fileOperations = new FileOperations();
            string filename = string.Format(@"{0}{1}{2}.Designer.cs", Directory.GetParent(project.FullName), Path.DirectorySeparatorChar, database.RemoveSpecialChar());
            string filenameHelper = string.Format(@"{0}{1}{2}Helper.cs", Directory.GetParent(project.FullName), Path.DirectorySeparatorChar, fileHelper.RemoveSpecialChar());

            var isSuccess = false;
            int i = 0;
            var foldername = "LocalDatabase";
            ProjectItem folder = null;
            while (!isSuccess && i < 101)
                try
                {
                    folder = project.ProjectItems.AddFolder(foldername);
                    isSuccess = true;
                }
                catch (Exception) { foldername = foldername + ++i; }

            filename = fileOperations.Write(filename, content.Replace("[LOCALDATABASE]", foldername), true);
            filenameHelper = fileOperations.Write(filenameHelper, contentHelper.Replace("[LOCALDATABASE]", foldername), false);

            if (null != folder) folder.ProjectItems.AddFromFileCopy(filename);
            if (null != folder) folder.ProjectItems.AddFromFileCopy(filenameHelper);

            fileOperations.Delete(filename);
            fileOperations.Delete(filenameHelper);


            return true;
        }

        /// <summary>
        /// Get Namespace information from selected ProjectItem
        /// </summary>
        /// <param name="projectItem"></param>
        /// <returns></returns>
        public string GetNamespace(ProjectItem projectItem)
        {
            if (null != projectItem && null != projectItem.FileCodeModel)
            {
                foreach (CodeElement element in projectItem.FileCodeModel.CodeElements)
                {
                    if (element.Kind == vsCMElement.vsCMElementNamespace)
                    {
                        return element.FullName;
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// Get Class Name information from selected ProjectItem
        /// </summary>
        /// <param name="projectItem"></param>
        /// <returns></returns>
        public string GetClassName(ProjectItem projectItem)
        {
            if (null != projectItem)
                return Path.GetFileNameWithoutExtension(projectItem.Name);

            return null;
        }

        /// <summary>
        /// Get Parent Project Item from selected ProjectItem
        /// </summary>
        /// <param name="project"></param>
        /// <param name="findItem"></param>
        /// <param name="filename"></param>
        /// <returns></returns>
        public ProjectItem GetProjectItem(ProjectItems project, string findItem, string filename)
        {
            ProjectItem projectItem = null;
            if (null != project)
                foreach (ProjectItem item in project)
                {
                    if (item.Name == findItem && IsProjectItemContains(item.ProjectItems, filename + ".cs"))
                        return item;
                    if (null != item.ProjectItems)
                    {
                        var result = GetProjectItem(item.ProjectItems, findItem, filename);
                        if (null != result) return result;
                    }

                }

            return projectItem;

        }


        /// <summary>
        /// Check ProjectItem contains given project item name
        /// </summary>
        /// <param name="projectItems"></param>
        /// <param name="contain"></param>
        /// <returns></returns>
        private bool IsProjectItemContains(ProjectItems projectItems, string contain)
        {


            if (null != projectItems)
            {
                foreach (ProjectItem item in projectItems)
                    if (contain.ToUpper() == item.Name.ToUpper())
                        return true;
            }

            return false;
        }
        #endregion

    }
}
